/*
 * JBoss, Home of Professional Open Source
 * Copyright 2011, Red Hat, Inc., and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.slaffka.security;

import javax.enterprise.event.Event;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.transaction.UserTransaction;

import com.slaffka.Authenticated;
import com.slaffka.i18.DefaultBundleKey;
import com.slaffka.model.Loan;
import com.slaffka.model.Role;
import com.slaffka.model.User;
import org.hibernate.Session;
import org.jboss.seam.faces.security.LoginListener;
import org.jboss.seam.international.status.Messages;
import org.jboss.seam.security.Authenticator;
import org.jboss.seam.security.BaseAuthenticator;
import org.jboss.seam.security.Credentials;
import org.jboss.seam.security.Identity;
import org.jboss.solder.logging.Logger;
import org.picketlink.idm.impl.api.PasswordCredential;
import org.picketlink.idm.impl.api.model.SimpleUser;

import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * This is the simplest possible example of a custom authenticator.
 *
 * @author Shane Bryzak
 * @author <a href="mailto:bleathem@gmail.com">Brian Leathem</a>
 */
public class SimpleAuthenticator extends BaseAuthenticator implements Authenticator {

    @Inject
    private Logger log;

    @PersistenceContext
    private EntityManager em;

    @Inject
    private Credentials credentials;


    @Inject
    private Messages messages;

    @Inject
    @Authenticated
    private Event<User> loginEventSrc;

    @Inject
    private Identity identity;

    public void authenticate() {
        log.info("Logging in " + credentials.getUsername());
        if ((credentials.getUsername() == null) || (credentials.getCredential() == null)) {
            messages.error(new DefaultBundleKey("identity_loginFailed")).defaults("Invalid username or password");
            setStatus(AuthenticationStatus.FAILURE);
        }
        System.out.println("~~~credential = " + credentials.getUsername() + ", pass = ");
        //User user = em.find(User.class, credentials.getUsername());
        User user = null;
        try {
            user = (User) em
                    .createQuery("select u from User u where u.username = :username")
                    .setParameter("username", credentials.getUsername())
                    .getSingleResult();
        } catch (Exception e){
            e.printStackTrace();
        }
        System.out.println("~~~user = " + user + ", pass = " + user.getPassword() + ", lenght = " + user.getPassword().length());
        if ( credentials.getCredential() instanceof PasswordCredential){
            PasswordCredential passwordCredential = (PasswordCredential) credentials.getCredential();
            System.out.println("~~~isPasswordCredential = " + passwordCredential.getValue() + ", passSize = " + passwordCredential.getValue().length());
        }
        if (user != null && credentials.getCredential() instanceof PasswordCredential &&
                user.getPassword().equals(((PasswordCredential) credentials.getCredential()).getValue())) {
            //loginEventSrc.fire(user);
            messages.info(new DefaultBundleKey("identity_loggedIn"), user.getUsername()).defaults("Вы авторизированы как {0}")
                    .params(user.getUsername());
            setStatus(AuthenticationStatus.SUCCESS);
            setUser(new SimpleUser(user.getUsername())); //TODO confirm the need for this set method
            for (Role role: user.getRoles()){
                identity.addRole(role.getRoleType().getRoleTypeStr(), "default", "default");
            }

            Long filialId = user.getFilial() != null ? user.getFilial().getFilialId() : null;

//            Session session = (Session)em.getDelegate();
//            session.enableFilter("currentFilial").setParameter("currentFilial", filialId);
//
//            session.getSessionFactory().getCurrentSession().enableFilter("currentFilial").setParameter("currentFilial", filialId);
            List<Loan> loans = em.createQuery("select l from Loan l").getResultList();
            for (Loan loan: loans){
                System.out.println("loan = " + loan.getContractId());
            }

            overrideRedirectToLogin();

            return;
        }

        messages.error(new DefaultBundleKey("identity_loginFailed")).defaults("Пара логин пароль неверна");
        setStatus(AuthenticationStatus.FAILURE);
    }

    private void overrideRedirectToLogin() {
        final String PRE_LOGIN_URL = LoginListener.class.getName() + "_PRE_LOGIN_URL";
        final ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();

        final Map<String, Object> sessionMap = externalContext.getSessionMap();
        String redirectURL = (String) sessionMap.get(PRE_LOGIN_URL);
        if (redirectURL == null) {

            final HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
            request.getParameter("javax.faces.ViewState");
            redirectURL = request.getRequestURL().toString();
        }
        if (redirectURL.indexOf(".jsf") > -1){
            System.out.println("url before = " + redirectURL);
            redirectURL = redirectURL.substring(0, redirectURL.indexOf(".jsf"));
            System.out.println("url after = " + redirectURL);
        }
        sessionMap.put(PRE_LOGIN_URL, redirectURL.replace("/login", "/loans"));
    }
}
